refactor: single-owner edge geometry pipeline + layout orchestrator - #53
Open
RhizoNymph wants to merge 10 commits into
Open
refactor: single-owner edge geometry pipeline + layout orchestrator#53RhizoNymph wants to merge 10 commits into
RhizoNymph wants to merge 10 commits into
Conversation
…tion # Conflicts: # docs/OVERVIEW.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integrates two refactor branches of the visualization layer (
refactor/edge-geometry-pipeline,refactor/layout-orchestrator), merged and seam-tested here. One PR, both halves reviewable via their own commit series.Why
Edge geometry had no single owner: an edge's polyline was mutated by ~6 loosely-coupled stages across three files, endpoint anchors were stored but never read (every consumer re-inferred them from geometry with three different tolerance heuristics), hit-testing measured a polyline that was not the one drawn, and PixiRenderer carried an untestable layout-orchestration state machine layering three staleness mechanisms.
What changed
Edge geometry (
refactor/edge-geometry-pipeline)edgeAnchorAtBoundary, exact segment-direction reading instead of tolerance ladders) and consumed by every later stage. DeletedinferEdgeAnchor/inferAnchorSide/inferApproachSide/inferAnchorsFromPolyline/inferPointSide.layout/edgeRoutePipeline.ts: the draw-time stage order is one function body —anchorEndpoints -> spreadEndpointLanes -> detourAroundObstacles, each a pure stage returning new records; a stage that moves an endpoint emits its updated anchor.edgeDrawing.tsis left with layer management and stroking.anchorEdgePolylinereports{ points, rerouted }instead of silently discarding ELK's route; surfaced asRoutedEdge.origin.layout/routingConstants.tsowns every routing tolerance/margin, with derived values expressed as arithmetic (OBSTACLE_QUERY_MARGIN = NODE_OBSTACLE_MARGIN + DETOUR_GUTTER + allowance) so they cannot drift. Hot-loop constants are re-bound as module-local consts inedgeGeometry.ts(V8 does not constant-fold live imported bindings; an interleaved A/B run isolated ~8% routing cost before the re-bind).edgeRoutingBudget.tsmovedrenderers/->layout/(it is a layout-side dependency);extractLayoutsplit into pure ELK-free functions (layout/elkExtract.ts).Layout orchestration (
refactor/layout-orchestrator)layout/layoutOrchestrator.tsowns the layout-request lifecycle previously inlined in PixiRenderer: the run-latest coalescing queue, the request-id stale guard, the pending gate on the cheap visibility redraw, and the latest-vs-applied visible-set reconciliation. All side effects injected, so the invariants are unit-tested with fakes (burst coalescing, stale-result discard, mid-flight visibility reconciliation, error path releasing the gate, edges-phase no-op before first layout).NodeRenderer,EdgeRenderer,LabelRenderer,interactionManager) are deleted.Integration (this branch)
tests/vizIntegrationSeam.test.tswires the real geometry chain in as the orchestrator's effects and pins the composed invariants neither half tests alone: every edge phase receives the newest APPLIED layout (including a previous edge phase's result) as its input, routed polylines survive edge-phase reruns through that adoption, and anchors and geometry still agree after the full draw-time pipeline (including lane-moved endpoints). Both docs' merge conflicts resolved by combining the halves.Edge-routing benchmark is at parity with main (all scenarios within run variance; 800n/500e indexed routing 251ms vs 259ms on main). Visual output is unchanged apart from the hit-test fix and rare anchor-side differences where the old tolerance ladder guessed wrong.